﻿using System;
using System.Linq;
using System.Web.Caching;
using Netkk.Common.Models;
using Netkk.Data.Provider;
using System.Collections.Generic;
using System.Xml.Linq;
using Netkk.Common;
using Netkk.Library;

namespace Netkk.Data
{
    public class XmlDataProvider : DataProvider
    {
        private string userPath;
        private string rolePath;
        private string linkPath;
        private string appointmentPath;
        private string contentPath;
        private string downloadPath;
        private string newsPath;

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            base.Initialize(name, config);

            userPath = string.Concat(ConnectionString, "Users.xml");
            rolePath = string.Concat(ConnectionString, "Roles.xml");
            linkPath = string.Concat(ConnectionString, "Links.xml");
            appointmentPath = string.Concat(ConnectionString, "Appointments.xml");
            contentPath = string.Concat(ConnectionString, "Content.xml");
            downloadPath = string.Concat(ConnectionString, "Downloads.xml");
            newsPath = string.Concat(ConnectionString, "News.xml");
        }

        #region Gecachter Zugriff auf das XDocument

        protected XDocument UserDocument
        {
            get { return CacheWrapper.Load("users", new CacheDependency(userPath), () => XDocument.Load(userPath)); }
        }

        protected XDocument RoleDocument
        {
            get { return CacheWrapper.Load("roles", new CacheDependency(rolePath), () => XDocument.Load(rolePath)); }
        }

        protected XDocument LinkDocument
        {
            get { return CacheWrapper.Load("links", new CacheDependency(linkPath), () => XDocument.Load(linkPath)); }
        }

        protected XDocument AppointmentDocument
        {
            get { return CacheWrapper.Load("appointments", new CacheDependency(appointmentPath), () => XDocument.Load(appointmentPath)); }
        }

        protected XDocument ContentDocument
        {
            get { return CacheWrapper.Load("content", new CacheDependency(contentPath), () => XDocument.Load(contentPath)); }
        }

        protected XDocument DownloadDocument
        {
            get { return CacheWrapper.Load("download", new CacheDependency(downloadPath), () => XDocument.Load(downloadPath)); }
        }

        protected XDocument NewsDocument
        {
            get { return CacheWrapper.Load("news", new CacheDependency(newsPath), () => XDocument.Load(newsPath)); }
        }

        #endregion

        #region User

        /// <summary>
        /// Selects all users.
        /// </summary>
        /// <returns></returns>
        public override IEnumerable<User> SelectAllUsers()
        {
            IEnumerable<User> users =
                from u in UserDocument.Element("Users").Elements("User")
                select getUserFromXElement(u);

            return users;
        }

        /// <summary>
        /// Gets the user from X element.
        /// </summary>
        /// <param name="XUser">The X user.</param>
        /// <returns></returns>
        private User getUserFromXElement(XElement XUser)
        {
            return new User
            {
                Id = XUser.Element("Id").Value.ToOrDefault<Guid>(),
                FirstName = XUser.Element("Name").Value,
                LastName = XUser.Element("SureName").Value,
                Email = XUser.Element("Email").Value,
                Image = XUser.Element("Image").Value,
                Website = XUser.Element("Website").Value,
                Description = XUser.Element("Description").Value,
                Role = getRoleById(XUser.Element("RoleId").Value.ToOrDefault<Guid>()),
                Name = XUser.Element("Login").Value,
                Password = XUser.Element("Password").Value,
                IsValid = XUser.Element("IsValid").Value.ToOrDefault<bool>(),
                AllowShowProfile = XUser.Element("AllowShowProfile").Value.ToOrDefault<bool>(),
                AllowSendNewsletter = XUser.Element("AllowSendNewsletter").Value.ToOrDefault<bool>(),
                AllowSendEmails = XUser.Element("AllowSendEmails").Value.ToOrDefault<bool>()
            };
        }

        /// <summary>
        /// Saves the user.
        /// </summary>
        /// <param name="user">The user.</param>
        public override void SaveUser(User user)
        {
            XElement xuser = (from u in UserDocument.Element("Users").Elements("User")
                              where u.Element("Id").Value.ToOrDefault<Guid>() == user.Id
                              select u).FirstOrDefault();
            if (xuser == null)
            {
                xuser = new XElement("User");
                UserDocument.Element("Users").Add(xuser);
            }
            else
            {
                xuser.RemoveAll();
            }

            xuser.Add(
                new XElement("Id")
                {
                    Value = user.Id.ToString("B")
                },
                new XElement("Name")
                {
                    Value = user.FirstName ?? String.Empty
                },
                new XElement("SureName")
                {
                    Value = user.LastName ?? String.Empty
                },
                new XElement("Email")
                {
                    Value = user.Email
                },
                new XElement("Website")
                {
                    Value = user.Website ?? String.Empty
                },
                new XElement("Image")
                {
                    Value = user.Image ?? String.Empty
                },
                new XElement("Description")
                {
                    Value = user.Description ?? String.Empty
                },
                new XElement("RoleId")
                {
                    Value = user.Role.Id.ToString("B")
                },
                new XElement("Login")
                {
                    Value = user.Name
                },
                new XElement("Password")
                {
                    Value = user.Password
                },
                new XElement("IsValid")
                {
                    Value = user.IsValid.ToString()
                },
                new XElement("AllowShowProfile")
                {
                    Value = user.AllowShowProfile.ToString()
                },
                new XElement("AllowSendNewsletter")
                {
                    Value = user.AllowSendNewsletter.ToString()
                },
                new XElement("AllowSendEmails")
                {
                    Value = user.AllowSendEmails.ToString()
                });

            UserDocument.Save(userPath);
        }

        /// <summary>
        /// Deletes the user.
        /// </summary>
        /// <param name="user">The user.</param>
        public override void DeleteUser(User user)
        {
            XElement xuser = (from u in UserDocument.Element("Users").Elements("User")
                              where u.Element("Id").Value.ToOrDefault<Guid>() == user.Id
                              select u).FirstOrDefault();
            if (xuser != null)
            {
                xuser.Remove();
                UserDocument.Save(userPath);
            }
        }

        #endregion

        #region Role

        /// <summary>
        /// 
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public override IEnumerable<UserRole> SelectAllRoles()
        {
            IEnumerable<UserRole> roles = from r in RoleDocument.Element("Roles").Elements("Role")
                                          select getRoleFromXElement(r);
            return roles;
        }

        private UserRole getRoleFromXElement(XElement XRole)
        {
            return new UserRole
            {
                Id = XRole.Element("Id").Value.ToOrDefault<Guid>(),
                Role = XRole.Element("Name").Value.ToOrDefault<Roles>()
            };
        }

        private UserRole getRoleById(Guid id)
        {
            IEnumerable<UserRole> roles = SelectAllRoles();
            UserRole role = (from r in roles
                             where r.Id == id
                             select r).FirstOrDefault();
            return role;
        }

        #endregion

        #region Link

        /// <summary>
        /// Selects all links.
        /// </summary>
        /// <returns></returns>
        public override IEnumerable<Link> SelectAllLinks()
        {
            IEnumerable<Link> links = from l in LinkDocument.Element("Links").Elements("Link")
                                      select getLinkFromXElement(l);
            return links;
        }

        /// <summary>
        /// Gets the link from X element.
        /// </summary>
        /// <param name="XLink">The X link.</param>
        /// <returns></returns>
        private Link getLinkFromXElement(XElement XLink)
        {
            return new Link
            {
                Id = XLink.Element("Id").Value.ToOrDefault<Guid>(),
                Name = XLink.Element("Name").Value,
                Url = XLink.Element("Url").Value,
                Description = XLink.Element("Description").Value,
                Order = XLink.Element("Order").Value.ToOrDefault<int>(),
                Category = XLink.Element("Category").Value,
            };
        }

        /// <summary>
        /// Saves the link.
        /// </summary>
        /// <param name="link">The link.</param>
        public override void SaveLink(Link link)
        {
            XElement xlink = (from l in LinkDocument.Element("Links").Elements("Link")
                              where l.Element("Id").Value.ToOrDefault<Guid>() == link.Id
                              select l).FirstOrDefault();
            if (xlink == null)
            {
                xlink = new XElement("Link");
                LinkDocument.Element("Links").Add(xlink);
            }
            else
            {
                xlink.RemoveAll();
            }

            xlink.Add(
                new XElement("Id")
                {
                    Value = link.Id.ToString("B")
                },
                new XElement("Name")
                {
                    Value = link.Name
                },
                new XElement("Url")
                {
                    Value = link.Url
                },
                new XElement("Description")
                {
                    Value = link.Description
                },
                new XElement("Order")
                {
                    Value = link.Order.ToString()
                },
                new XElement("Category")
                {
                    Value = link.Category
                });

            LinkDocument.Save(linkPath);
        }

        /// <summary>
        /// Deletes the link.
        /// </summary>
        /// <param name="link">The link.</param>
        public override void DeleteLink(Link link)
        {
            XElement xlink = (from l in LinkDocument.Element("Links").Elements("Link")
                              where l.Element("Id").Value.ToOrDefault<Guid>() == link.Id
                              select l).FirstOrDefault();
            if (xlink != null)
            {
                xlink.Remove();
                LinkDocument.Save(linkPath);
            }
        }

        #endregion

        #region Appointment

        /// <summary>
        /// Selects all contents.
        /// </summary>
        /// <returns></returns>
        public override IEnumerable<Appointment> SelectAllAppointments()
        {
            IEnumerable<Appointment> appointments = from c in AppointmentDocument.Element("Appointments").Elements("Appointment")
                                                    select getAppointmentFromXElement(c);
            return appointments;
        }

        /// <summary>
        /// Gets the appointment from X element.
        /// </summary>
        /// <param name="XAppointment">The X appointment.</param>
        /// <returns></returns>
        private Appointment getAppointmentFromXElement(XElement XAppointment)
        {
            return new Appointment
            {
                Id = XAppointment.Element("Id").Value.ToOrDefault<Guid>(),
                Title = XAppointment.Element("Title").Value,
                ShortTitle = XAppointment.Element("ShortTitle").Value,
                Date = XAppointment.Element("Date").Value.ToOrDefault<DateTime>(),
                Location = XAppointment.Element("Location").Value,
                Teaser = XAppointment.Element("Teaser").Value,
                Description = XAppointment.Element("Description").Value
            };
        }

        /// <summary>
        /// Saves the appointment.
        /// </summary>
        /// <param name="appointment">The appointment.</param>
        public override void SaveAppointment(Appointment appointment)
        {
            XElement xcontent = (from c in AppointmentDocument.Element("Appointments").Elements("Appointment")
                                 where c.Element("Id").Value.ToOrDefault<Guid>() == appointment.Id
                                 select c).FirstOrDefault();
            if (xcontent == null)
            {
                xcontent = new XElement("Appointment");
                AppointmentDocument.Element("Appointments").Add(xcontent);
            }
            else
            {
                xcontent.RemoveAll();
            }

            xcontent.Add(
                new XElement("Id")
                {
                    Value = appointment.Id.ToString("B")
                },
                new XElement("Title")
                {
                    Value = appointment.Title
                },
                new XElement("ShortTitle")
                {
                    Value = appointment.ShortTitle
                },
                new XElement("Date")
                {
                    Value = appointment.Date.ToString("dd.MM.yyyy HH:mm:ss")
                },
                new XElement("Location")
                {
                    Value = appointment.Location
                },
                new XElement("Teaser")
                {
                    Value = appointment.Teaser
                },
                new XElement("Description")
                {
                    Value = appointment.Description
                });

            AppointmentDocument.Save(appointmentPath);
        }

        /// <summary>
        /// Deletes the appointment.
        /// </summary>
        /// <param name="appointment">The appointment.</param>
        public override void DeleteAppointment(Appointment appointment)
        {
            XElement xcontent = (from c in AppointmentDocument.Element("Appointments").Elements("Appointment")
                                 where c.Element("Id").Value.ToOrDefault<Guid>() == appointment.Id
                                 select c).FirstOrDefault();
            if (xcontent != null)
            {
                xcontent.Remove();
                AppointmentDocument.Save(appointmentPath);
            }
        }

        #endregion

        #region Content

        /// <summary>
        /// Selects all contents.
        /// </summary>
        /// <returns></returns>
        public override IEnumerable<Content> SelectAllContents()
        {
            IEnumerable<Content> contents = from c in ContentDocument.Element("Contents").Elements("Content")
                                            select getContentFromXElement(c);
            return contents;
        }

        /// <summary>
        /// Gets the content from XElement.
        /// </summary>
        /// <param name="XContent">Content of the XElement</param>
        /// <returns></returns>
        private Content getContentFromXElement(XElement XContent)
        {
            return new Content
            {
                Name = XContent.Element("Name").Value,
                PageTitle = XContent.Element("PageTitle").Value,
                PageDescription = XContent.Element("PageDescription").Value,
                PageKeywords = XContent.Element("PageKeywords").Value,
                PageContent = XContent.Element("PageContent").Value
            };
        }


        /// <summary>
        /// Deletes the content.
        /// </summary>
        /// <param name="content">The content.</param>
        public override void DeleteContent(Content content)
        {
            XElement xcontent = (from c in ContentDocument.Element("Contents").Elements("Content")
                                 where c.Element("Name").Value.Equals(content.Name, StringComparison.InvariantCultureIgnoreCase)
                                 select c).FirstOrDefault();
            if (xcontent != null)
            {
                xcontent.Remove();
                ContentDocument.Save(contentPath);
            }
        }

        /// <summary>
        /// Saves the content.
        /// </summary>
        /// <param name="content">The content.</param>
        public override void SaveContent(Content content)
        {
            XElement xcontent = (from c in ContentDocument.Element("Contents").Elements("Content")
                                 where c.Element("Name").Value.Equals(content.Name, StringComparison.InvariantCultureIgnoreCase)
                                 select c).FirstOrDefault();
            if (xcontent == null)
            {
                xcontent = new XElement("Content");
                ContentDocument.Element("Contents").Add(xcontent);
            }
            else
            {
                xcontent.RemoveAll();
            }

            xcontent.Add(
                new XElement("Name")
                {
                    Value = content.Name
                },
                new XElement("PageTitle")
                {
                    Value = content.PageTitle
                },
                new XElement("PageDescription")
                {
                    Value = content.PageDescription
                },
                new XElement("PageKeywords")
                {
                    Value = content.PageKeywords
                },
                new XElement("PageContent")
                {
                    Value = content.PageContent
                });

            ContentDocument.Save(contentPath);
        }

        #endregion

        #region Download


        /// <summary>
        /// Selects all downloads.
        /// </summary>
        /// <returns></returns>
        public override IEnumerable<Download> SelectAllDownloads()
        {
            IEnumerable<Download> download = from l in DownloadDocument.Element("Downloads").Elements("Download")
                                             select getDownloadFromXElement(l);
            return download;
        }

        /// <summary>
        /// Gets the link from X element.
        /// </summary>
        /// <param name="XDownload">The X download.</param>
        /// <returns></returns>
        private Download getDownloadFromXElement(XElement XDownload)
        {
            return new Download
            {
                Id = XDownload.Element("Id").Value.ToOrDefault<Guid>(),
                Name = XDownload.Element("Name").Value,
                ContentType = XDownload.Element("ContentType").Value,
                ContentSize = XDownload.Element("ContentSize").Value.ToOrDefault<int>(),
                FileName = XDownload.Element("FileName").Value,
                Description = XDownload.Element("Description").Value,
            };
        }

        /// <summary>
        /// Deletes the download.
        /// </summary>
        /// <param name="download">The download.</param>
        public override void DeleteDownload(Download download)
        {
            XElement xdownload = (from d in DownloadDocument.Element("Downloads").Elements("Download")
                                  where d.Element("Id").Value.ToOrDefault<Guid>() == download.Id
                                  select d).FirstOrDefault();
            if (xdownload != null)
            {
                xdownload.Remove();
                DownloadDocument.Save(downloadPath);
            }
        }

        /// <summary>
        /// Saves the download.
        /// </summary>
        /// <param name="download">The download.</param>
        public override void SaveDownload(Download download)
        {
            XElement xdownload = (from d in DownloadDocument.Element("Downloads").Elements("Download")
                                  where d.Element("Id").Value.ToOrDefault<Guid>() == download.Id
                                  select d).FirstOrDefault();
            if (xdownload == null)
            {
                xdownload = new XElement("Download");
                DownloadDocument.Element("Downloads").Add(xdownload);
            }
            else
            {
                xdownload.RemoveAll();
            }

            xdownload.Add(new XElement("Id") { Value = download.Id.ToString("B") },
                      new XElement("Name") { Value = download.Name },
                      new XElement("ContentType") { Value = download.ContentType },
                      new XElement("ContentSize") { Value = download.ContentSize.ToString() },
                      new XElement("FileName") { Value = download.FileName },
                      new XElement("Description") { Value = download.Description });
            DownloadDocument.Save(downloadPath);
        }

        #endregion

        #region News

        /// <summary>
        /// Selects all news.
        /// </summary>
        /// <returns></returns>
        public override IEnumerable<News> SelectAllNews()
        {
            IEnumerable<News> appointments = from c in NewsDocument.Element("News").Elements("Message")
                                             select getNewsFromXElement(c);
            return appointments;
        }

        /// <summary>
        /// Gets the news from X element.
        /// </summary>
        /// <param name="XNews">The X news.</param>
        /// <returns></returns>
        private News getNewsFromXElement(XElement XNews)
        {
            return new News
            {
                Id = XNews.Element("Id").Value.ToOrDefault<Guid>(),
                Date = XNews.Element("Date").Value.ToOrDefault<DateTime>(),
                Title = XNews.Element("Title").Value,
                Teaser = XNews.Element("Teaser").Value,
                Text = XNews.Element("Text").Value
            };
        }

        /// <summary>
        /// Saves the appointment.
        /// </summary>
        /// <param name="news">The news.</param>
        public override void SaveNews(News news)
        {
            XElement xcontent = (from c in NewsDocument.Element("News").Elements("Message")
                                 where c.Element("Id").Value.ToOrDefault<Guid>() == news.Id
                                 select c).FirstOrDefault();
            if (xcontent == null)
            {
                xcontent = new XElement("Message");
                NewsDocument.Element("News").Add(xcontent);
            }
            else
            {
                xcontent.RemoveAll();
            }

            xcontent.Add(
                new XElement("Id") { Value = news.Id.ToString("B") },
                new XElement("Date") { Value = news.Date.ToString("dd.MM.yyyy HH:mm:ss") },
                new XElement("Title") { Value = news.Title },
                new XElement("Teaser") { Value = news.Teaser },
                new XElement("Text") { Value = news.Text });

            NewsDocument.Save(newsPath);
        }

        /// <summary>
        /// Deletes the News.
        /// </summary>
        /// <param name="news">The News.</param>
        public override void DeleteNews(News news)
        {
            XElement xcontent = (from c in NewsDocument.Element("News").Elements("Message")
                                 where c.Element("Id").Value.ToOrDefault<Guid>() == news.Id
                                 select c).FirstOrDefault();
            if (xcontent != null)
            {
                xcontent.Remove();
                NewsDocument.Save(newsPath);
            }
        }

        #endregion

    }
}
